#include <sys/epoll.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#include <vector>
#include <cstring>
#include <chrono>

#define MAX_EVENTS 1024
#define BUFFER_SIZE 2048

const uint32_t PORT = 8080;

int set_nonblocking(int fd) {
    int flags = fcntl(fd, F_GETFL, 0);
    return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

int main() {
    // 创建监听socket
    int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (listen_fd == -1) {
        perror("socket");
        return 1;
    }

    // 设置地址重用
    int opt = 1;
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    // 绑定地址
    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT); // 监听8080端口
    addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(listen_fd, (sockaddr*)&addr, sizeof(addr)) == -1) {
        perror("bind");
        return 1;
    }

    // 开始监听
    if (listen(listen_fd, SOMAXCONN) == -1) {
        perror("listen");
        return 1;
    }

    // 创建epoll实例
    int epoll_fd = epoll_create1(0);
    if (epoll_fd == -1) {
        perror("epoll_create");
        return 1;
    }

    // 添加监听socket到epoll
    epoll_event event{};
    event.events = EPOLLIN;
    event.data.fd = listen_fd;
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &event) == -1) {
        perror("epoll_ctl");
        return 1;
    }

    std::vector<epoll_event> events(MAX_EVENTS);
    std::string received_data;

    std::cout << "Echo server started on port: " << PORT << std::endl;
    while (true) {
        int n = epoll_wait(epoll_fd, events.data(), MAX_EVENTS, -1);
        if (n == -1) {
            perror("epoll_wait");
            return 1;
        }

        for (int i = 0; i < n; ++i) {
            received_data.clear();
            // 处理新连接
            if (events[i].data.fd == listen_fd) {

                // auto tp0 = std::chrono::high_resolution_clock::now();

                sockaddr_in client_addr{};
                socklen_t addr_len = sizeof(client_addr);
                int client_fd = accept(listen_fd, (sockaddr*)&client_addr, &addr_len);
                if (client_fd == -1) {
                    perror("accept");
                    continue;
                }

                set_nonblocking(client_fd);

                // 添加新客户端到epoll
                epoll_event client_event{};
                client_event.events = EPOLLIN | EPOLLET;
                client_event.data.fd = client_fd;
                if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &client_event) == -1) {
                    perror("epoll_ctl");
                    close(client_fd);
                }

                // auto tp1 = std::chrono::high_resolution_clock::now();
                // auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>(tp1 - tp0).count();
                // std::cout << "Accept time: " << duration1 << "us" << std::endl;

            }
            // 处理客户端数据
            else {
                // auto tp0 = std::chrono::high_resolution_clock::now();

                char buf[BUFFER_SIZE];

                // 循环读取直到数据读完
                while (true) {
                    ssize_t bytes_read = read(events[i].data.fd, buf, sizeof(buf));
                    if (bytes_read > 0) {
                        received_data.append(buf, bytes_read);
                    }
                    else if (bytes_read == 0 || (bytes_read == -1 && errno != EAGAIN)) {
                        // 连接关闭或错误
                        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, events[i].data.fd, nullptr);
                        close(events[i].data.fd);
                        break;
                    }
                    else {
                        // 数据读取完毕（遇到EAGAIN）
                        // 回写所有接收到的数据
                        std::string response = "HTTP/1.1 200 OK\r\nContent-Length: " +
                            std::to_string(received_data.size()) +
                            "\r\n\r\n" + received_data;
                        write(events[i].data.fd, response.c_str(), response.size());
                        break;
                    }
                }

                // auto tp1 = std::chrono::high_resolution_clock::now();
                // auto duration1 = std::chrono::duration_cast<std::chrono::microseconds>(tp1 - tp0).count();
                // std::cout << "Read time: " << duration1 << "us" << std::endl;

            }
        }
    }

    close(listen_fd);
    return 0;
}
